-
Notifications
You must be signed in to change notification settings - Fork 39
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Introduce assorted Reactor StepVerifier
Refaster rules
#1132
Conversation
Looks good. No mutations were possible for these changes. |
/** | ||
* Prefer {@link StepVerifier.LastStep#verifyErrorSatisfies(Consumer)} with AssertJ over more | ||
* contrived alternatives. | ||
*/ | ||
static final class StepVerifierLastStepVerifyErrorSatisfiesAssertJ { | ||
@BeforeTemplate | ||
void before(StepVerifier.LastStep step, Class<? extends Throwable> clazz, String message) { | ||
Refaster.anyOf( | ||
step.expectError() | ||
.verifyThenAssertThat() | ||
.hasOperatorErrorOfType(clazz) | ||
.hasOperatorErrorWithMessage(message), | ||
step.expectError(clazz).verifyThenAssertThat().hasOperatorErrorWithMessage(message), | ||
step.expectErrorMessage(message).verifyThenAssertThat().hasOperatorErrorOfType(clazz)); | ||
} | ||
|
||
@AfterTemplate | ||
@UseImportPolicy(STATIC_IMPORT_ALWAYS) | ||
void after(StepVerifier.LastStep step, Class<? extends Throwable> clazz, String message) { | ||
step.verifyErrorSatisfies( | ||
t -> Assertions.assertThat(t).isInstanceOf(clazz).hasMessage(message)); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Asserting both class and message blocks one to use the recommended StepVerifier.Step#verifyError(Class)
or StepVerifier.Step#verifyErrorMessage(String)
. Choosing an alternative isn't easy since there are many possibilities. Out of all the options, AssertJ's assertions have the richest API, so I'd recommend this.
The StepVerifierVerify
rule introduced in this PR aims to rewrite the use-cases in which only one of class or message are asserted by dropping the StepVerifier.Assertions
type which allows other rules to rewrite further.
/** | ||
* Prefer {@link StepVerifier.LastStep#verifyErrorMatches(Predicate)} over more verbose | ||
* alternatives. | ||
*/ | ||
static final class StepVerifierLastStepVerifyErrorMatchesAssertions { | ||
@BeforeTemplate | ||
void before(StepVerifier.LastStep step, Predicate<Throwable> predicate) { | ||
step.expectError().verifyThenAssertThat().hasOperatorErrorMatching(predicate); | ||
} | ||
|
||
@AfterTemplate | ||
void after(StepVerifier.LastStep step, Predicate<Throwable> predicate) { | ||
step.verifyErrorMatches(predicate); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This case is not exhaustive due to the overload of StepVerifier.LastStep#expectedError
, but IMO covers sufficiently.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can collapse this one into the preceding method.
/** Don't unnecessarily invoke {@link StepVerifier#verifyLater()} multiple times. */ | ||
static final class StepVerifierVerifyLater<T> { | ||
@BeforeTemplate | ||
StepVerifier before(StepVerifier stepVerifier) { | ||
return stepVerifier.verifyLater().verifyLater(); | ||
} | ||
|
||
@AfterTemplate | ||
StepVerifier after(StepVerifier stepVerifier) { | ||
return stepVerifier.verifyLater(); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The API spec mentions this is a noop. I didn't fully understand why this API may be useful for in the first place.
7395f93
to
0eea3ac
Compare
Looks good. No mutations were possible for these changes. |
1 similar comment
Looks good. No mutations were possible for these changes. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added a commit. Tnx @werli!
/** | ||
* Prefer {@link StepVerifier.LastStep#verifyErrorMatches(Predicate)} over more verbose | ||
* alternatives. | ||
*/ | ||
static final class StepVerifierLastStepVerifyErrorMatchesAssertions { | ||
@BeforeTemplate | ||
void before(StepVerifier.LastStep step, Predicate<Throwable> predicate) { | ||
step.expectError().verifyThenAssertThat().hasOperatorErrorMatching(predicate); | ||
} | ||
|
||
@AfterTemplate | ||
void after(StepVerifier.LastStep step, Predicate<Throwable> predicate) { | ||
step.verifyErrorMatches(predicate); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can collapse this one into the preceding method.
Mono.empty() | ||
.as(StepVerifier::create) | ||
.expectError() | ||
.verifyThenAssertThat() | ||
.hasOperatorErrorOfType(IllegalStateException.class) | ||
.hasOperatorErrorWithMessage("foo"); | ||
Mono.empty() | ||
.as(StepVerifier::create) | ||
.expectError(IllegalStateException.class) | ||
.verifyThenAssertThat() | ||
.hasOperatorErrorWithMessage("bar"); | ||
Mono.empty() | ||
.as(StepVerifier::create) | ||
.expectErrorMessage("baz") | ||
.verifyThenAssertThat() | ||
.hasOperatorErrorOfType(IllegalStateException.class); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can use three different Throwable
types like a bit further up.
*/ | ||
static final class StepVerifierVerify { | ||
@BeforeTemplate | ||
void before(StepVerifier stepVerifier) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While in this case arguably incorrect, we do generally match any expression, even if that can lead to compilation errors. (At least this will force the user to clean up the code.)
I'll apply those changes to this PR, though I could also see us change our mind on that in the future.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My intent was indeed to avoid breaking code changes by only matching the "dangling" case in which the created StepVerifier.Assertions
isn't used or cases we should clearly rewrite.
StepVerifier#verifyThenAssertThat
has some valid yet niche usages, see internal usages. Sure, we could suppress the warning here, but IMO the warning would be a false positive. WDYT?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay - I've given this another thought. Let's proceed as-is, and violations could be suppressed through the warning. The internal use cases are quite sparse.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Discussed offline: I do think @werli has a good point. Ideally we have our cake and eat it too (i.e., have separate "aggressive" and "safe" modes). I'll add a comment describing the current thinking of what that could look like.
Looks good. No mutations were possible for these changes. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice improvements!
3742218
to
fcbda80
Compare
Looks good. No mutations were possible for these changes. |
Quality Gate passedIssues Measures |
fcbda80
to
8f803e0
Compare
^ Rebased to resolve conflicts. IMO, we can proceed. 👍 |
Looks good. No mutations were possible for these changes. |
1 similar comment
Looks good. No mutations were possible for these changes. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added a commit, summarizing what we discussed offline. Let's merge after #1387 is merged and released.
Looks good. No mutations were possible for these changes. |
The build fails due to what appears to be a bug in JDK 23. Will require further investigation later ~today. |
Will require attaching a debugger, I think, for which I'll need to find more time. Observations so far:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The last changes LGTM, thanks @Stephan202 💪
Interesting bug investigation. What do we do in this scenario for error-prone-support
? Change our code & report, or report & leave the PR open until it's fixed? The latter may take a while.
Discussed offline: certainly we'll want to proceed with this PR. Whatever workaround we go for, ideally we do link it to a bug report. This would likely entail the following steps:
Depending on availability one of us will have a crack at this. |
f7b1121
to
cee4b2c
Compare
Alright, I rebased and added a commit. Turns out the bug is in all versions preceding JDK 23: There are no |
Looks good. No mutations were possible for these changes. |
Quality Gate passedIssues Measures |
💡💡💡 Thanks @Stephan202 💪 |
Summary
This PR introduces a bunch of rules associated to
StepVerifier.Asserations
and a trivialStepVerifier
rule.Example
I spotted the following interesting pattern:
Which made me find the interesting
StepVerifier#Assertions
API. It's quite low-level, and IMO not as straightforward to read and write.The example itself is most often represented in our code-base using AssertJ's richer API:
Suggested commit message: